package zero.tech.games.mj.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import zero.tech.core.ZeroContext;
import zero.tech.core.data.Resp;
import zero.tech.games.common.Code;
import zero.tech.games.logic.common.Room;
import zero.tech.games.logic.util.LogicUtil;
import zero.tech.games.mj.data.MjBigPanel;
import zero.tech.games.mj.data.MjConfig;
import zero.tech.games.mj.data.MjGameBase;
import zero.tech.games.mj.data.MjRoomCache;
import zero.tech.games.mj.data.MjTimer;
import zero.tech.games.mj.data.consts.GameConst;
import zero.tech.games.mj.data.consts.MJCMD;
import zero.tech.games.mj.data.consts.MjConst;
import zero.tech.games.mj.data.entity.PlayerBigCal;
import zero.tech.games.mj.data.entity.PlayerData;
import zero.tech.games.mj.data.notify.NotifyCtrlCard;
import zero.tech.games.mj.data.res.ResSpCtrlCard;
import zero.tech.games.mj.service.api.IMjService;
import zero.tech.wsnet.controller.Controller;
import zero.tech.wsnet.controller.LogicController;
import zero.tech.wsnet.data.Message;

/**
 * 游戏分支逻辑（玩家操作牌(1过,2碰,3杠,4胡)）
 * @author JackQu
 */
public class GameLogic {
	
	private static final Logger logger = LoggerFactory.getLogger(GameLogic.class);
	
	/**
	 * 处理请求操作牌
	 * @param room
	 * @param controller
	 * @param info
	 * @param type
	 */
	public static void disposeReqCtrlCard(Room room, LogicController controller, String info, int type){
		// TODO Auto-generated method stub
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		PlayerData player = gameBase.getPlayerUid(controller.getId());
		String[] ctrType = new String[] { "过", "碰", "明杠", "接炮胡", "暗杠", "点杠", "自摸" };
		int card = -1;
		if (info == null || info.equals("")) {
			card = gameBase.getCurrCard();
		} else {
			String[] split = info.split(",");
			card = Integer.parseInt(split[0]);
		}
		try {
			int[] card2 = CardUtil.getCard(card);
			String[] tt = new String[] { "万", "条", "同" };
			logger.info("----" + player.getUid() + "----" + card + "-----" + player.getNick() + "玩家操作牌:  " + card2[1] + "-" + tt[card2[3]]  + "---" + ctrType[type - 1] + "---");
			if (type == MjConst.PASS) {
				if (player.getActionArr().isEmpty()) {
					return;
				}
				logger.info("玩家：--》" + player.getUid() + " 可以操作--》" + player.getActionArr() + " 却点了过");
				controller.getWebClient().sendMessage(
						Message.build(MJCMD.RES_CTRL_CARD, Resp.build(Code.OK, "操作成功")));
				detailUserPass(player, card, type, room);
			} else {
				// 判断自己是否可以做该操作
				if (!isContainCtrl(player.getActionArr(), type)) {
					return;
				}
				if (type != MjConst.HU && type != MjConst.HU_ZM) {
					removeCtrlCard(gameBase, player.getUid(), card);
					// 判断是否有玩家要胡牌, 如果要胡牌则等待其他玩家
					if (!checkIsHu(player, gameBase)) {
						if (checkSelfIsHu(player, gameBase)) {
							gameBase.clearHuInfo(player.getUid());
						}
						controller.getWebClient().sendMessage(Message.build(MJCMD.RES_CTRL_CARD, Resp.build(Code.OK, "操作成功")));
						switch (type) {
						case MjConst.PENG:
							donePeng(player, card, room);
							break;
						default:
							doneGang(player, controller, card, type, room);
							break;
						}
					} else {
						controller.getWebClient().sendMessage(Message.build(MJCMD.RES_CTRL_CARD, Resp.build(Code.SERVER_ERROR, "请等待其他玩家操作")));
					}
				} else {
					if (!player.isWin()) {
						controller.getWebClient().sendMessage(Message.build(MJCMD.RES_CTRL_CARD, Resp.build(Code.OK, "操作成功")));
						removeCtrlCard(gameBase,player.getUid(), card);
						doneHu(player, card, type, room);
					} else {
						controller.getWebClient().sendMessage(Message.build(MJCMD.RES_CTRL_CARD, Resp.build(Code.SERVER_ERROR, "不能胡牌")));
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 检查是否有该操作
	 * @param actionArr
	 * @param type
	 * @return
	 */
	public static boolean isContainCtrl(List<String> actionArr, int type) {
		for (int i = 0; i < actionArr.size(); i++) {
			String string = actionArr.get(i);
			String[] split = string.split("_");
			if (Integer.valueOf(split[0]) == type) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 处理玩家过
	 * @param vo
	 * @param card
	 * @param type
	 * @throws Exception
	 */
	private static void detailUserPass(PlayerData player, int card, int type, Room room){
		// TODO Auto-generated method stub
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		IMjService gameService = ZeroContext.getInstance(IMjService.class);
		// 一炮多响的时候下个玩家摸牌位置的问题
		if (!"".equals(gameBase.getHuSStr()) && !checkIsHu(player, gameBase)) {
			String[] huSStr = gameBase.getHuSStr().split(",");
			gameBase.updateCurrCtrl(new Integer(huSStr[1]), new Integer(huSStr[0]));
			gameBase.setHuSStr("");
		}
		if (!checkIsHu(player, gameBase)) {
			checkQiangGang(room);
		}

		if (gameBase.getOperData() != null && gameBase.getOperData().getUid() != player.getUid()) {
			if (checkIsHu(player, gameBase)) {
				gameBase.setPassInfo(player.getUid(), false);
				if (gameBase.getHuArr().size() > 1) {
					gameBase.removeHuArrByUid(player.getUid());
					if (checkIsHu(gameBase)) {
						// 设置庄
						if (gameBase.getHuArr().size() == 1
								&& gameBase.getHuid() == 0) {
							int uid = gameBase.getHuArr().get(0);
							gameBase.setHuid(uid);
							gameBase.updateCurrCtrl(card, uid);
						}
					}
				}
				gameBase.clearHuInfo(player.getUid());
			}
			// 过牌后清理他的数据
			addPassCard(player, card);
			player.initActionArr();
			sendCtrlMsg(player, type, card, room);
			if (checkIsNull(player, gameBase)) {
				gameBase.addOperPlayback(card + "_1_" + player.getUid() + "_" + gameBase.getCardBank().size());
				showLogs(" 过牌后打印日志 ", player);
				gameBase.clearHuInfo();
				gameBase.setGangInfo(0, 0);
				if (checkIsHu(gameBase)) {
					if (!checkIsHu(player, gameBase)) {
						IMjService service=ZeroContext.getInstance(IMjService.class);
						service.gameOver(room);
					}
				} else {
					gameService.nextGetCard(false, room);
				}
			} else {
				PlayerData playerVo = gameBase.getOperData();
				if (checkIsNull(playerVo, gameBase)) {
					if (playerVo.getActionArr().size() > 0) {
						// 包含补杠操作
						if (isContainCtrl(playerVo.getActionArr(), MjConst.GANG)) {
							int cardd = -1;
							for (int i = 0; i < playerVo.getActionArr().size(); i++) {
								String string = playerVo.getActionArr().get(i);
								String charAt = string.substring(0, 1);
								if (Integer.valueOf(charAt) == MjConst.GANG) {
									String[] split = string.split("_");
									cardd = Integer.valueOf(split[1]);
									break;

								}
							}
							playerVo.addGangStr(countTmpScore(playerVo, 1, 0, MjConst.GANG, "明杠", cardd, gameBase));
							playerVo.setBuGang(true);
							gameBase.setGetCard(true);
							String info = GameUtils.addMingGangInfo(cardd, playerVo);
							gameBase.addOperPlayback(info + "_"
									+ MjConst.GANG + "_" + playerVo.getUid()
									+ "_"
									+ gameBase.getCardBank().size()
									+ "_" + gameBase.getOperData().getUid());
							showLogs(" 明杠后打印日志 ", playerVo);
							playerVo.removeHandCard(cardd);
							getGangCtrl(playerVo, cardd, MjConst.GANG, room);
						}
					}
				}
			}
		}
	}

	/**
	 * 处理杠后炮，转雨的操作，一个人胡了，则要把杠分给他，还有其他人胡则杠分丢失
	 * @param room
	 */
	public static void checkQiangGang(Room room) {
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		List<Integer> huList = gameBase.getHuList();
		if (huList.size() == 1 && gameBase.getCanHu().size() > 1 && !gameBase.isQiangGang()) {
			// TODO 杠分处理
			PlayerData mvo = gameBase.getPlayerUid(huList.get(0));
			String GL = gameBase.getGangLast();
			if (!"".equals(GL)) {
				logger.info(mvo.getUid() + "转雨成功            " + GL);
				mvo.addGangStr(GL);
			}
		}
	}

	/**
	 * 抢杠过
	 * @param player
	 * @param card
	 */
	private static void addPassCard(PlayerData player, int card) {
		if (player.getActionArr().indexOf(MjConst.HU + "") != -1) {
			player.getPassArr().add(card);
		}
	}

	/**
	 * 处理碰牌
	 * @param player
	 * @param card
	 * @param room
	 * @throws Exception
	 */
	private static void donePeng(PlayerData player, int card, Room room){
		// TODO Auto-generated method stub
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		MjTimer mjTimer = (MjTimer) room.getTimer();
		player.setOut(true);
		gameBase.setGangInfo(0, 0);
		gameBase.setPassInfo(player.getUid(), true);
		addCtrlCard(player.getTmpArr(), MjConst.PENG, player, card, gameBase);
		sendCtrlMsg(player, MjConst.PENG, card, room);
		player.initActionArr();
		gameBase.updateCurrCtrl(card, player.getUid());
		// ext.roomRnner.updateTime();
		mjTimer.setLastTimer(System.currentTimeMillis());
	}
	
	/**
	 * 处理杠牌
	 * @param player
	 * @param sender
	 * @param card
	 * @param type
	 * @param room
	 */
	private static void doneGang(PlayerData player, Controller sender, int card, int type, Room room){
		// TODO Auto-generated method stub
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		MjConfig mjConfig = gameBase.getMjConfig();
		if (checkHaveGange(player.getGlist(), card)) {
			gameBase.setGangInfo(player.getUid(), type);
			switch (type) {
			case MjConst.AN_GANG:
				gameBase.setGetCard(true);
				player.addGangStr(countTmpScore(player, 2, 0, MjConst.AN_GANG, "暗杠", card, gameBase));
				addCtrlCard(player.getTmpGangArr(), type, player, card, gameBase);
				// vo.setGangStr(vo.getGangStr()+"暗杠");
				getGangCtrl(player, card, type, room);
				break;
			case MjConst.DI_GANG:
				gameBase.setGetCard(true);
				// 点杠刮风是否开启
				player.addGangStr(countTmpScore(player, 3, gameBase.getOperData().getUid(), MjConst.DI_GANG, "点杠", card, gameBase));
				addCtrlCard(player.getTmpGangArr(), type, player, card, gameBase);
				getGangCtrl(player, card, type, room);
				break;
			default: // 明杠

				if (!player.isBuGang()) {
					if (mjConfig.getGameType() != 2)
						checkSpCtrl(player, card, room);
					else {
						checkSpCtrl1(player, card, room);
					}
				}
				if (!player.isBuGang()) {
					player.addGangStr(countTmpScore(player, 1, 0, MjConst.GANG, "明杠", card, gameBase));
					player.setBuGang(true);
				}

				if (!checkIsHu(player, gameBase)) {
					gameBase.setGetCard(true);
					String info = GameUtils.addMingGangInfo(card, player);
					gameBase.addOperPlayback(info + "_" + type + "_"
							+ player.getUid() + "_"
							+ gameBase.getCardBank().size() + "_"
							+ gameBase.getOperData().getUid());
					showLogs(" 明杠后打印日志 ", player);
					player.removeHandCard(card);
					getGangCtrl(player, card, type, room);
				}
				break;
			}
		}

	}

	/**
	 * 检查是否可以杠这张牌
	 * @param glist
	 * @param card
	 * @return
	 */
	private static boolean checkHaveGange(List<String> glist, int card) {
		for (int i = 0; i < glist.size(); i++) {
			int[] arr = GameUtils.getIntArr(glist.get(i), "_");
			if (arr[1] == card) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 当某个玩家胡牌后删除其他玩家的碰,杠
	 * @param gameBase
	 */
	private static void clearActionState(MjGameBase gameBase) {
		for (PlayerData mvo : gameBase.getPlayerMap().values()) {
			String tmp = "";
			List<String> actionArr = mvo.getActionArr();
			for (String string : actionArr) {
				String[] split = string.split("_");
				if (Integer.valueOf(split[0]) == MjConst.HU) {
					tmp = string;
				}
			}
			mvo.getActionArr().clear();
			if ("" != tmp && !tmp.isEmpty()) {
				mvo.getActionArr().add(tmp);
			}
		}
	}

	/**
	 * 处理杠牌操作
	 * @param Player
	 * @param card
	 * @param type
	 * @param room
	 */
	private static void getGangCtrl(PlayerData Player, int card, int type, Room room){
		// TODO Auto-generated method stub
		IMjService gameService = ZeroContext.getInstance(IMjService.class);
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		Player.getGlist().clear();
		gameBase.updateCurrCtrl(card, Player.getUid());
		sendCtrlMsg(Player, type, card, room);
		Player.initActionArr();
		Player.addFan(1);
		gameService.nextGetCard(true, room);
	}

	/**
	 * 添加特殊操作牌
	 * @param list
	 * @param type
	 * @param player
	 * @param card
	 * @param gameBase
	 */
	private static void addCtrlCard(List<Integer> list, int type, PlayerData player, int card, MjGameBase gameBase){
		List<Integer> arr = getGangList(list, card);
		// 明杠需要删除手上的牌
		if (type == MjConst.GANG) {
			player.removeHandCard(card);
		}
		String byArr = GameUtils.getStrByArr(arr);
		player.removeHandCard(arr);
		String str = byArr + "_" + type + "_" + player.getUid() + "_"
				+ gameBase.getOperData().getUid();
		if (type == MjConst.AN_GANG) {
			gameBase.addOperPlayback(byArr + "_" + type + "_" + player.getUid()
					+ "_" + gameBase.getCardBank().size() + "_"
					+ gameBase.getOperData().getUid());
			showLogs(" 暗杠后打印日志 ", player);
			player.addCtrlCard(str);
		} else {
			gameBase.addOperPlayback(card + "," + byArr + "_" + type + "_"
					+ player.getUid() + "_"
					+ gameBase.getCardBank().size() + "_"
					+ gameBase.getOperData().getUid());
			showLogs(" 杠后打印日志 ", player);
			player.addCtrlCard(card + "," + str);
		}
	}

	/**
	 * 获取能杠的几张牌
	 * @param list
	 * @param card
	 * @return
	 */
	private static List<Integer> getGangList(List<Integer> list, int card) {
		List<Integer> value = new ArrayList<Integer>();
		int[] arr = CardUtil.getCard(card);
		for (int i = 0; i < list.size(); i++) {
			int[] tmp = CardUtil.getCard(list.get(i));
			if (arr[3] == tmp[3] && arr[1] == tmp[1]) {
				value.add(list.get(i));
			}
		}
		return value;
	}

	/**
	 * 完成胡牌
	 * @param player
	 * @param card
	 * @param type
	 * @param room
	 */
	public static void doneHu(PlayerData player, int card, int type, Room room){
		// TODO Auto-generated method stub
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		MjRoomCache extendCache = (MjRoomCache) room.getRoomCache();
		MjConfig mjConfig = gameBase.getMjConfig();
		// if(H100Utils.isHaveNum(ext.ftype, GameConst.F_7))
		logger.info("胡牌");
		MjBigPanel bigPanel = (MjBigPanel) extendCache.getBigPanel();
		PlayerBigCal calRole = bigPanel.getRoles().get(player.getUid());
		if (gameBase.getCanHu().size() > 1) {// 记录已经赢的玩家,用于记录杠一炮多响抢杠分
			gameBase.getHuList().add(player.getUid());
		}
		player.setWin(true);
		player.setCurrCard(card);
		calRole.setHuTimes(calRole.getHuTimes() + 1);
		if (type == MjConst.HU) {
			player.addHandlCard(card); // 接炮需要把放炮的这张放到手牌里
			player.getHuCards().add(card);
			player.setHuType(GameConst.WIN_JIEPAO);
			if (calRole != null) {
				calRole.setWinTimes(calRole.getWinTimes() + 1);
			}
		} else {
			player.setHuType(GameConst.WIN_ZIMO);
			player.getHuCards().add(card);
			calRole.setZimoTimes(calRole.getZimoTimes() + 1);
		}
		gameBase.setHupai(card);
		// 根据是否无鬼胡牌设置底分
		boolean isNoGui = true;
		List<Integer> handCard = player.getHandCard();
		for (Integer integer : handCard) {
			boolean guiPai = CardUtil.isGuiPai(integer, gameBase.getGuiCards());
			if (guiPai) {
				isNoGui = false;
				break;
			}
		}
		if (isNoGui) {
			player.setDiFen(4);
		} else {
			player.setDiFen(2);
		}

		// 玩家胡的顺序
		int huSort = 0;
		for (PlayerData sortVo : gameBase.getPlayerMap().values()) {
			if (sortVo.isWin() && sortVo.getHuSort() != -1) {
				huSort = huSort > sortVo.getHuSort() ? huSort : sortVo
						.getHuSort();
			}
		}
		huSort = huSort == 0 ? 1 : huSort + 1;
		player.setHuSort(huSort);
		// //////////////////////////
		sendCtrlMsg(player, type, card, room);
		gameBase.addOperPlayback(card + "_" + type + "_" + player.getUid() + "_" + gameBase.getCardBank().size() + "_" + player.getHuSort());
		showLogs(" 胡后打印日志 ", player);
		if (mjConfig.getGameType() == 1) {
			detailGangInfo(player, type, card, room);
		}

		List<Integer> idList = getIdList(gameBase);
		clearActionState(gameBase);
		// 统计放炮
		if (type == MjConst.HU) {
			PlayerData mvo = gameBase.getOperData();
			mvo.setDianPao(true);
			player.setLoseArr(Arrays.asList(mvo.getUid()));
			PlayerBigCal calRole2 = bigPanel.getRoles().get(mvo.getUid());
			logger.info("id{}点炮玩家次数统计{}", mvo.getUid(), calRole2);
			if (calRole2 != null) {
				calRole2.setDianPaoTimes(calRole2.getDianPaoTimes() + 1);
			}
		} else {
			player.setLoseArr(idList);
		}
		// 定庄的座位//一炮多响定庄问题
		if (gameBase.getCanHu().size() > 1
				&& gameBase.getHuList().size() > 1) {
			int haveWin = gameBase.getHuList().size();
			List<Integer> loser = player.getLoseArr();
			// ControllerData loseMpv = CowUtils.getPlayerVo(loser.get(0));
			PlayerData loseMpv = gameBase.getPlayerUid(loser.get(0));
			if ((haveWin == 2 && idList.size() == 2) || (haveWin == 3 && idList.size() == 1)) {
				gameBase.setHuid(loseMpv.getUid());
			}
			extendCache.setNextHostUid(loseMpv.getUid());
		} else {
			if (huSort == 1) {
				gameBase.setHuid(player.getUid());
				extendCache.setNextHostUid(player.getUid());
			}
		}
		logger.info("胡牌后庄家id：" + gameBase.getHuid());

		if (gameBase.getOperData().getUid() == player.getUid()) {
			player.setSpHuStr(player.getSpHuStr() + " 自摸");
		}
		logger.info("DoneHu胡牌翻数算法: " + player.getFanNum());
		// 判断剩余的玩家
		if (!checkIsHu(player, gameBase)) {
			IMjService service=ZeroContext.getInstance(IMjService.class);
			service.gameOver(room);
		} else {
			gameBase.addHuCount(1);
			player.initActionArr();
		}
	}
	
	/**
	 * 获取未胡玩家id集合
	 * @param gameBase
	 * @return
	 */
	private static List<Integer> getIdList(MjGameBase gameBase) {
		List<Integer> idList = new ArrayList<Integer>();
		for (PlayerData mvo : gameBase.getPlayerMap().values()) {
			if (!mvo.isWin()) {
				idList.add(mvo.getUid());
			}
		}
		return idList;
	}

	/**
	 * 杠牌信息
	 * @param player
	 * @param type
	 * @param card
	 * @param room
	 */
	private static void detailGangInfo(PlayerData player, int type, int card, Room room) {
		// 判断是否是杠上花
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		if (gameBase.getdGangUid() != 0) {
			PlayerData mpv = gameBase.getPlayerMap().get(gameBase.getdGangUid());
			logger.info("上个玩家:" + gameBase.getdGangUid() + " 杠类型：" + gameBase.getdGangType());
			String Ganglast = "";
			/** 判断特殊胡 */
			if (!"".equals(gameBase.getGangLast())) {
				Ganglast = gameBase.getGangLast();// 得到临时存储的最后一个家的杠数据
			}
			boolean flag = false;// 判断是不是抢杠胡
			String lastMG = "";// 临时记录最后一个杠的信息
			if ("".equals(Ganglast)) {
				List<String> Gl = mpv.getGangArr();
				if (Gl.size() >= 1)
					lastMG = Gl.get(Gl.size() - 1);
			} else {
				lastMG = Ganglast;
			}
			if (!"".equals(lastMG))
				flag = getIsAdd(lastMG, card);
			String str = "";
			if (mpv.getUid() == player.getUid()) {
				// 杠上花
				str = "杠上花";
			}else if (gameBase.getdGangType() == MjConst.GANG && flag) {
				// 抢杠胡
				gameBase.setQiangGang(true);
				str = "抢杠胡";
			}else {
				// 杠上炮
				str = "杠后炮";
			}
			if (player.getSpHuStr().indexOf(str) == -1) {
				player.setSpHuStr(str);
			}
			logger.info("玩家：" + player.getUid() + " " + player.getSpHuStr());
			/** 判断特殊胡结束 */

			/** 转雨操作 */
			if (type == MjConst.HU)// 胡炮，
			{
				if (!"".equals(Ganglast)) {
					logger.info(player.getUid() + "晚啦，已经被别人抢了");
					mpv.removeHandCard(card);
				} else {
					logger.info("抢杠删除前的信息：", mpv.getGangArr());
					String gl = mpv.removeGangLast();
					gameBase.setGangLast(gl);
					logger.info("抢杠删除[后] 的信息：", mpv.getGangArr(), " 枪杠"
							+ gl, "胡牌:" + card);
					// 明杠抢杠后删除杠牌玩家的牌//抢明杠，分会丢失
					if (gameBase.getdGangType() == MjConst.GANG) {
						mpv.removeHandCard(card);
					}
					if (gameBase.getCanHu().size() == 1
							&& !getIsAdd(gl, card)) {
						// 刚后炮点炮玩家删除杠,不算分
						mpv.getGangArr().add(gl);
					}
				}
			}
			player.addFan(1);
		}
	}

	/**
	 * 判断是否是刚上炮(抢杠)
	 * @param last
	 * @param card
	 * @return
	 */
	private static boolean getIsAdd(String last, int card) {
		String[] ids = last.split(",");
		int value = GameUtils.getInteger(ids[ids.length - 1]);
		if (value == card)
			return true;
		return false;
	}

	/**
	 * 广播玩家操作(1过,2碰,3明杠,4胡,5暗杠,6点杠)
	 * @param player
	 * @param type
	 * @param card
	 * @param room
	 */
	private static void sendCtrlMsg(PlayerData player, int type, int card, Room room){
		NotifyCtrlCard packageNotifyCtrlCard = PackageUtil.packageNotifyCtrlCard(player, type, card, room);
		LogicUtil.broadRoomAllControllersInclude(room, Message.build(
				MJCMD.NOTIFY_CTRL_CARD, Resp.build(Code.OK, "广播玩家操作",packageNotifyCtrlCard)));
	}

	/**
	 * 检测除开自己的玩家是否可以有特殊操作
	 * @param player
	 * @param gameBase
	 * @return
	 */
	private static boolean checkIsHu(PlayerData player, MjGameBase gameBase){
		for (PlayerData mvo : gameBase.getPlayerMap().values()) {
			if (player.getUid() != mvo.getUid()) {
				if (!mvo.isWin()) {
					if (isContainCtrl(mvo.getActionArr(), MjConst.HU)) {
						return true;
					}
				}
			}
		}
		return false;
	}

	/**
	 * 检测是否有玩家胡牌
	 * @param gameBase
	 * @return
	 */
	private static boolean checkIsHu(MjGameBase gameBase){
		for (PlayerData mvo : gameBase.getPlayerMap().values()) {
			if (mvo.isWin()) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 检测除开自己的玩家是否可以有特殊操作
	 * @param player
	 * @param gameBase
	 * @return
	 * @throws Exception
	 */
	private static boolean checkSelfIsHu(PlayerData player, MjGameBase gameBase)
			throws Exception {
		for (PlayerData mvo : gameBase.getPlayerMap().values()) {
			if (player.getUid() == mvo.getUid()) {
				if (!mvo.isWin()) {
					if (mvo.getActionArr().indexOf(MjConst.HU + "") != -1) {
						return true;
					}
				}
			}
		}
		return false;
	}

	/**
	 * 检测其他人是否还有操作
	 * @param vo
	 * @param gameBase
	 * @return
	 */
	private static boolean checkIsNull(PlayerData vo, MjGameBase gameBase){
		for (PlayerData mvo : gameBase.getPlayerMap().values()) {
			if (vo.getUid() != mvo.getUid()) {
				if (!mvo.isWin()) {
					if (mvo.getActionArr().size() > 0) {
						return false;
					}
				}
			}
		}
		return true;
	}

	/**
	 * 删除自己的牌
	 * @param gameBase
	 * @param uid
	 * @param card
	 */
	private static void removeCtrlCard(MjGameBase gameBase, int uid, int card) {
		for (PlayerData mvo : gameBase.getPlayerMap().values()) {
			if (uid != mvo.getUid()) {
				mvo.removeOutCard(card);
			}
		}
	}

	/**
	 * 临时积分
	 * @param player
	 * @param score
	 * @param uUid 点杠玩家id(自杠为0)
	 * @param type 操作类型(-1减分, 1加分)
	 * @param msg
	 * @param card
	 * @param gameBase
	 * @return
	 */
	public static String countTmpScore(PlayerData player, int score, int uUid, int type, String msg, int card, MjGameBase gameBase) {
		String str = "";
		String str1 = "";
		for (PlayerData mvo : gameBase.getPlayerMap().values()) {
			if (player.getUid() != mvo.getUid()) {
				if (!mvo.isWin()) {
					if (uUid == 0) {
						str += mvo.getUid() + ",";
						str1 += mvo.getNick() + ",";
					} else if (uUid == mvo.getUid()) {
						str = mvo.getUid() + ",";
						str1 = mvo.getNick() + ",";
						break;
					}
				}
			}
		}
		str += score + "," + type + "," + card;
		logger.info("临时积分【" + msg + "】" + str);
		logger.info("临时积分【" + msg + "】" + str1);
		return str;
	}


	/**
	 * 日志输出记录
	 */
	public static void showLogs(String str, PlayerData vo) {
		logger.info("********************" + vo.toString());
		logger.info(" 玩家：" + vo.getUid() + " 玩家nick:" + vo.getNick() + str + "---");
	}
	
	
	/**
	 * 检测玩家自己的操作
	 * @param player
	 * @param card
	 * @param isSelf
	 * @param isCheckSp
	 * @param room
	 * @return
	 */
	public static boolean checkSelfCtrl(PlayerData player, int card, boolean isSelf, boolean isCheckSp, Room room){
		// TODO Auto-generated method stub
		boolean isCheck = false;
		if (isCheckSp) {
			isCheck = checkSpCtrl(player, card, isSelf, room);
		}
		sendCtrlCard(player, card, room);
		return isCheck;
	}
	
	
	/**
	 * 检查特殊操作牌
	 * @param player
	 * @param card
	 * @param isSelf
	 * @param room
	 * @return
	 */
	public static boolean checkSpCtrl(PlayerData player, int card, boolean isSelf, Room room){
		// TODO Auto-generated method stub
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		player.setHandCard(CardUtil.getNewList(player.getHandCard()));
		boolean isCheck = false;
		List<String> tmp = new ArrayList<String>();
		player.getGlist().clear();
		player.getTmpGangArr().clear();
		player.getTmpArr().clear();
		MjConfig mjConfig = gameBase.getMjConfig();
		if (!isSelf) {
			boolean guiPai = false;
			if (gameBase.getGuiCards().size() > 0) {
				for (int i = 0; i < gameBase.getGuiCards().size(); i++) {
					int[] car1 = CardUtil.getCard(card);
					int[] car2 = CardUtil.getCard(gameBase.getGuiCards().get(i));
					if (car1[1] == car2[1] && car1[3] == car2[3]) {
						guiPai = true;
					}
				}
			}
			if (!guiPai) {
				isCheck = CardUtil.checkPengGPai(player.getHandCard(), player.getTmpArr(), card, 2);
				if (isCheck) {
					boolean canPeng = false;
					List<Integer> disObtainGhost = CardUtil.getDisObtainGhost(player.getHandCard(), room);
					for (Integer integer : disObtainGhost) {
						if (!CardUtil.isSameCard(card, integer)) {
							canPeng = true;
							break;
						}
					}
					if (canPeng) {
						tmp.add("" + MjConst.PENG);
					}
				}
				if (gameBase.getCardBank().size() > 0 || mjConfig.getHaiDiGang() == 1) {
					isCheck = CardUtil.checkPengGPai(player.getHandCard(), player.getTmpGangArr(), card, 3);
					if (isCheck) {
						tmp.add("" + MjConst.DI_GANG + "_" + card);
						player.getGlist().add(MjConst.DI_GANG + "_" + card);
					}
				}
			}
			boolean isPass = true;
			player.addHandlCard(card); // 临时做计算用
			player.setHandCard(CardUtil.getNewList(player.getHandCard()));
			List<Integer> guiCard = CardUtil.getObtainGhost(player.getHandCard(), room);
			List<Integer> notGuiCard = CardUtil.getDisObtainGhost(player.getHandCard(), room);
			isCheck = false;
			if (mjConfig.getJiePaoHu() == 1 || (mjConfig.getQiangGangHu() == 1 && gameBase.isGrabBar())) {
				isCheck = MjHuUtil.checkHu(notGuiCard, guiCard, mjConfig.getGameType() == 1, mjConfig);
			}
			if (isCheck) {
				if (isPass) {
					tmp.add("" + MjConst.HU + "_" + card);
					gameBase.getCanHu().add(player.getUid());
					int count = 1;
					player.setFanCount(count);
					gameBase.addHuUid(player.getUid()); // 添加胡牌玩家
				} // 过胡胡大的判断
				else {
					tmp.add("" + MjConst.HU + "_" + card);
					gameBase.getCanHu().add(player.getUid());
					gameBase.addHuUid(player.getUid()); // 添加胡牌玩家
				}
			}
			player.removeHandCard(card);
		} // 检测玩家自己明杠或暗杠
		else {
			if (gameBase.getCardBank().size() > 0 || mjConfig.getHaiDiGang() == 1) {
				// 检测手中的明杠
				checkHandGang(tmp, player, card, mjConfig.getPassGang() == 1);
				// 检测手中的杠(本来就有的杠)
				isCheck = CardUtil.checkGangPai(player.getHandCard(), player.getTmpGangArr(), 
						player.getGlist(), gameBase.getGuiCards());
				if (isCheck && GameLogic.isContainCtrl(player.getGlist(), MjConst.AN_GANG)) {
					tmp.addAll(player.getGlist());
				}
			}
			List<Integer> guiCard = CardUtil.getObtainGhost(player.getHandCard(), room);
			List<Integer> notGuiCard = CardUtil.getDisObtainGhost(player.getHandCard(), room);
			// 如果手牌全部是鬼牌,强制胡牌
			boolean allGui = false;
			if (player.getHandCard().size() != guiCard.size()) {
				isCheck = MjHuUtil.checkHu(notGuiCard, guiCard, mjConfig.getGameType() == 1, mjConfig);
			} else {
				isCheck = true;
				allGui = true;
			}
			if (isCheck) {
				if(allGui && mjConfig.getGameType() == 1){
					tmp.add("" + MjConst.HU_ZM + "_" + card + "_1");
				}else{
					tmp.add("" + MjConst.HU_ZM + "_" + card);
				}
			}
			logger.info(player.getUid() + "自摸：" + isCheck);
		}
		// 去重
		List<String> tmp2 = new ArrayList<String>();
		for (int i = 0; i < tmp.size(); i++) {
			String str = tmp.get(i);
			if (!tmp2.contains(str)) {
				tmp2.add(str);
			}
		}
		logger.info(player.getNick() + "(" + player.getUid() + ")   操作:" + tmp2, tmp2.size());
		player.setActionArr(tmp2);
		return tmp2.size() > 0;
	}
	
	/**
	 * 发送特殊控制信息
	 * @param player
	 * @param card
	 * @param room
	 */
	private static void sendCtrlCard(PlayerData player, int card, Room room){
		if (!player.getActionArr().isEmpty()) {
			String byArr = GameUtils.getStrByArr(player.getGlist(), ",");
			LogicController controller = player.getController(room);
			ResSpCtrlCard packageNotifySpCtrlCard = PackageUtil.packageResSpCtrlCard(player, card);
			controller.getWebClient().sendMessage(Message.build(
					MJCMD.RES_SP_CTRL_CARD, Resp.build(Code.OK, "通知特殊操作牌",packageNotifySpCtrlCard)));
			logger.info("检测" + player.getUid() + player.getNick() + "玩家有以下操作"
					+ GameUtils.getTypeInfo(player.getActionArr()) + "(类型(2,3,4)2碰,3明杠,4胡,5暗杠,6点杠,7自摸)");
			logger.info("杠牌的数据:: " + byArr);
		}
	}
	
	/**
	 * 检测手中的明杠
	 * @param tmp
	 * @param player
	 * @param card
	 * @param passGang 过之后能否补杠 true能 false 不能
	 */
	private static void checkHandGang(List<String> tmp, PlayerData player, int card, boolean passGang) {
		if (player.getCtrlCard().size() > 0) {
			boolean isCheck = false;
			if (passGang) {
				for (int i = 0; i < player.getHandCard().size(); i++) {
					int value = player.getHandCard().get(i);
					isCheck = CardUtil.checkMingGang(value, player.getCtrlCard());
					if (isCheck) {
						tmp.add("" + MjConst.GANG + "_" + value);
						player.getGlist().add(MjConst.GANG + "_" + value);
					}
				}
			} else {
				int value = card;
				isCheck = CardUtil.checkMingGang(value, player.getCtrlCard());
				if (isCheck) {
					tmp.add("" + MjConst.GANG + "_" + value);
					player.getGlist().add(MjConst.GANG + "_" + value);
				}
			}
		}
	}
	
	/**
	 * 检测除开自己的玩家是否可以有特殊操作
	 * @param player
	 * @param card
	 * @param room
	 * @return 返回true 没有特殊操作, false 有特殊操作
	 */
	public static boolean checkSpCtrl1(PlayerData player, int card, Room room){
		boolean isNoSp = true;
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		MjConfig mjConfig = gameBase.getMjConfig();
		for (PlayerData mvo : gameBase.getPlayerMap().values()) {
			if (player.getUid() != mvo.getUid() && !mvo.isWin()) {
				checkSelfCtrl(mvo, card, false, true, room);
			}
		}
		for (PlayerData mvo : gameBase.getPlayerMap().values()) {
			if (player.getUid() != mvo.getUid() && mvo.isWin()) {
				mvo.setHandCard(CardUtil.getNewList(mvo.getHandCard()));
				mvo.removeHandCard(mvo.getCurrCard());
				mvo.addHandlCard(card);
				CardUtil.getPai(mvo.getHandCard());
				mvo.setHandCard(CardUtil.getNewList(mvo.getHandCard()));
				mvo.getActionArr().clear();
				List<Integer> guiCard = CardUtil.getObtainGhost(player.getHandCard(), room);
				boolean hu = MjHuUtil.checkHu(player.getHandCard(), guiCard, mjConfig.getGameType() == 1, mjConfig);
				if (hu) {
					mvo.removeHandCard(card);
					Vector<String> action = new Vector<String>();
					action.add(MjConst.HU + "");
					mvo.setActionArr(action);
				} else {
					mvo.removeHandCard(card);
					mvo.addHandlCard(mvo.getCurrCard());
				}
			}
		}
		isNoSp = GameUtils.check(gameBase);
		for (PlayerData playerVo : gameBase.getPlayerMap().values()) {
			if (player.getUid() != playerVo.getUid() && playerVo.isWin()) {
				if (!playerVo.getActionArr().isEmpty()) {
					GameLogic.doneHu(playerVo, card, MjConst.HU, room);
				}
			}
		}
		return isNoSp;
	}
	
	/**
	 * 检测除开自己的玩家是否可以有特殊操作
	 * @param player
	 * @param card
	 * @param room
	 * @return 返回true 没有特殊操作, false 有特殊操作
	 */
	public static boolean checkSpCtrl(PlayerData player, int card, Room room){
		boolean isNoSp = true;
		boolean isCheck = false;
		MjGameBase gameBase = (MjGameBase) room.getGameBase();
		for (PlayerData mvo : gameBase.getPlayerMap().values()) {
			if (player.getUid() != mvo.getUid() && !mvo.isWin()) {
				isCheck = checkSelfCtrl(mvo, card, false, true, room);
				if (isNoSp && isCheck)
					isNoSp = false;
			}
		}
		return isNoSp;
	}

}
